
local jass = require 'jass.common'
local dbg = require 'jass.debug'
local rect = require 'types.rect'
local circle = require 'types.circle'
local fogmodifier = require 'types.fogmodifier'
local ignore_flag = false
local ac_game = ac.game
local default_model = 'Environment\\DNC\\DNCLordaeron\\DNCLordaeronTerrain\\DNCLordaeronTerrain.mdl'
--注册颜色代码
local color_word = {}
color_word [1] = "|cFFFF0303"
color_word [2] = "|cFF0042FF"
color_word [3] = "|cFF1CE6B9"
color_word [4] = "|cFF540081"
color_word [5] = "|cFFFFFC01"
color_word [6] = "|cFFFE8A0E"
color_word [7] = "|cFF20C000"
color_word [8] = "|cFFE55BB0"
color_word [9] = "|cFF959697"
color_word[10] = "|cFF7EBFF1"
color_word[11] = "|cFFFFFC01"
color_word[12] = "|cFF0042FF"
color_word[13] = "|cFF282828"
color_word[14] = "|cFF282828"
color_word[15] = "|cFF282828"
color_word[16] = "|cFF282828"

local player = class('player')
player.type = 'player'        --类型
player.gold = 0               --金钱
player.gold_pool = 0          --零钱
player.mouse_x = 0            --鼠标x
player.mouse_y = 0            --鼠标y

function player:ctor(handle, idx)
	self.handle = handle        --句柄
	self.id = idx               --id

    self:Init()
end

function player:Init()

end

function player:__tostring()
    return ('玩家%02d|%s|%s'):format(self.id, self.base_name, jass.GetPlayerName(self.handle))
end

--region 事件
--注册事件
function player:event(name)
	return ac.event_register(self, name)
end

--发起事件
function player:event_dispatch(name, ...)
	local res = ac.event_dispatch(self, name, ...)
	if res ~= nil then
		return res
	end
	local res = ac.event_dispatch(ac_game, name, ...)
	if res ~= nil then
		return res
	end
	return nil
end

function player:event_notify(name, ...)
	ac.event_notify(self, name, ...)
	ac.event_notify(ac_game, name, ...)
end
--endregion

--region 属性
--获取玩家id
function player:get()
    return self.id
end

--获取玩家名字
function player:get_name()
	return jass.GetPlayerName(self.handle)
end

--获取原始名字
function player:getBaseName()
	return self.base_name
end

--设置玩家名字
function player:setName(name)
	jass.SetPlayerName(self.handle, name)
end

--是否是玩家
function player:is_player()
	return jass.GetPlayerController(self.handle) == jass.MAP_CONTROL_USER and jass.GetPlayerSlotState(self.handle) == jass.PLAYER_SLOT_STATE_PLAYING
end

--是否是裁判
function player:isObserver()
	return jass.IsPlayerObserver(self.handle)
end

--是否是本地玩家
function player:is_self()
	return self == g_playerMgr.self
end

--设置颜色
--	参数为颜色的id
function player:setColor(this, c)
	jass.SetPlayerColor(this.handle, c - 1)
end

--可见性检查
--位置的可见性
--	目标位置
function player:is_visible(where)
    local x, y = where:get_point():get()
    return jass.IsVisibleToPlayer(x, y, self.handle)
end

--是否是敌人
--	目标玩家
function player:is_enemy(dest)
    return self:get_team() ~= dest:get_team()
end

--是否是友军
function player:is_ally(dest)
    return self:get_team() == dest:get_team()
end
--endregion

--region 结盟/队伍
function player:setAlliance(dest, al, flag)
    return jass.SetPlayerAlliance(self.handle, dest.handle, al, flag)
end

function player:setAllianceSimple(dest, flag)
    jass.SetPlayerAlliance(self.handle, dest.handle, 0, flag)		--ALLIANCE_PASSIVE
    jass.SetPlayerAlliance(self.handle, dest.handle, 1, false)	--ALLIANCE_HELP_REQUEST
    jass.SetPlayerAlliance(self.handle, dest.handle, 2, false)	--ALLIANCE_HELP_RESPONSE
    jass.SetPlayerAlliance(self.handle, dest.handle, 3, flag)		--ALLIANCE_SHARED_XP
    jass.SetPlayerAlliance(self.handle, dest.handle, 4, flag)		--ALLIANCE_SHARED_SPELLS
    jass.SetPlayerAlliance(self.handle, dest.handle, 5, flag)		--ALLIANCE_SHARED_VISION
    --jass.SetPlayerAlliance(self, dest, 6, flag)	--ALLIANCE_SHARED_CONTROL
    --jass.SetPlayerAlliance(self, dest, 7, flag)	--ALLIANCE_SHARED_ADVANCED_CONTROL
    --jass.SetPlayerAlliance(self, dest, 8, flag)	--ALLIANCE_RESCUABLE
    --jass.SetPlayerAlliance(self, dest, 9, flag)	--ALLIANCE_SHARED_VISION_FORCED
end

--设置队伍
function player:setTeam(team_id)
    jass.SetPlayerTeam(self.handle, team_id - 1)
    self.team_id = team_id
end

--获取队伍
function player:get_team()
    if not self.team_id then
        self.team_id = jass.GetPlayerTeam(self.handle) + 1
    end
    return self.team_id
end
--endregion

--允许控制
--	[显示头像]
function player:enableControl(dest, flag)
	jass.SetPlayerAlliance(dest.handle, self.handle, 6, true)
	if flag then
		jass.SetPlayerAlliance(dest.handle, self.handle, 7, true)
	end
end
	
--显示系统警告
--	警告内容
function player:showSysWarning(msg)
    local sys_sound = jass.CreateSoundFromLabel("InterfaceError", false, false, false, 10, 10);
    if(jass.GetLocalPlayer() == self.handle) then
        if (msg ~= '') and (msg ~= nil) then
            jass.ClearTextMessages();
            jass.DisplayTimedTextToPlayer(self.handle, 0.5, -1, 2, '|cffffcc00' .. msg .. '|r');
        end
        jass.StartSound(sys_sound);
    end
    jass.KillSoundWhenDone(sys_sound);
end

--小地图
--	信号位置
--	信号时间
--	[红色]
--	[绿色]
--	[蓝色]
function player:pingMinimap(where, time, red, green, blue, flag)
	if self == g_playerMgr.self then
		local x, y = where:get_point():get()
		jass.PingMinimapEx(x, y, time, red or 0, green or 255, blue or 0, not not flag)
	end
end

--region 家当
--获得金钱
--	金钱数量
--	[漂浮文字显示位置]
--	[不抛出加钱事件]
function player:addGold(gold, where, flag)
	if gold > 0 and not flag then
		local data = {player = self, gold = gold}
		self:event_notify('玩家-即将获得金钱', data)
		gold = data.gold
	end
	gold = gold + self.gold_pool
	self.gold_pool = gold % 1
	gold = math.floor(gold)
	self.gold = self.gold + gold
	jass.SetPlayerState(self.handle, 0x01, self.gold)
	if not where or gold <= 0 then
		return
	end
	if not where:is_visible(self) then
		where = self.hero
		if not where then
			return
		end
	end
	local x, y = where:get_point():get()
	local z = where:get_point():getZ()
	local position = ac.point(x - 30, y, z + 30)
	ac.texttag
	{
		string = '+' .. math.floor(gold),
		size = 12,
		position = position,
		speed = 86,
		red = 100,
		green = 100,
		blue = 20,
		player = self,
		show = ac.texttag.SHOW_SELF
	}
	if where.type == 'unit' then
		local model
		if self:is_self() then
			model = [[UI\Feedback\GoldCredit\GoldCredit.mdl]]
		else
			model = ''
		end
		where:add_effect('overhead', model):remove()
	end
end
--增加，获取玩家木材，已使用人口
function player.addlumber(self,lumber)
	jass.SetPlayerState(self.handle,jass.PLAYER_STATE_RESOURCE_LUMBER,jass.GetPlayerState(self.handle,jass.PLAYER_STATE_RESOURCE_LUMBER)+lumber)
end
function player.addusedfood(self,food)
	jass.SetPlayerState(self.handle,jass.PLAYER_STATE_RESOURCE_FOOD_USED,jass.GetPlayerState(self.handle,jass.PLAYER_STATE_RESOURCE_FOOD_USED)+food)
end
function player.getlumber(self)
	return jass.GetPlayerState(self.handle,jass.PLAYER_STATE_RESOURCE_LUMBER)
end
function player.getusedfood(self)
	return jass.GetPlayerState(self.handle,jass.PLAYER_STATE_RESOURCE_FOOD_USED)
end
--获得玩家身上的钱
function player:getGold()
	return self.gold
end
--endregion

--region 技能
--禁用技能
function player:enable_ability(ability_id)
    if ability_id then
        jass.SetPlayerAbilityAvailable(self.handle, base.string2id(ability_id), true)
    end
end

function player:disable_ability(ability_id)
    if ability_id then
        jass.SetPlayerAbilityAvailable(self.handle, base.string2id(ability_id), false)
    end
end

--获得玩家指定位置技能id(War3中的id)
--	技能类型
--	技能位置
function player:get_ability_id(type, slotid)
    local list = self.ability_list
    if not list then
        return nil
    end
    if not list[type] then
        return nil
    end
    return list[type][slotid]
end
--endregion

--region 强制按键
--	按下的键(字符串'ESC'表示按下ESC键)
function player:pressKey(key)
	if self ~= g_playerMgr.self then
		return
	end

	local key = key:upper()
	
	if key == 'ESC' then
		jass.ForceUICancel()
	else
		jass.ForceUIKey(key)
	end
end
--endregion

--region 消息
--发送消息
--	消息内容
--	[持续时间]
function player:sendMsg(text, time)
	jass.DisplayTimedTextToPlayer(self.handle, 0, 0, time or 60, text)
end

--清空屏幕显示
function player:clearMsg()
	if self == g_playerMgr.self then
		jass.ClearTextMessages()
	end
end
--endregion

--region 摄像机
--设置镜头位置
function player:setCamera(where, time)
	if g_playerMgr.self == self then
		local x, y
		if where then
			x, y = where:get_point():get()
		else
			x, y = jass.GetCameraTargetPositionX(), jass.GetCameraTargetPositionY()
		end
		if time then
			jass.PanCameraToTimed(x, y, time)
		else
			jass.SetCameraPosition(x, y)
		end
	end
end

--设置镜头属性
--	镜头属性
--	数值
--	[持续时间]
function player:setCameraField(key, value, time)
	if self == g_playerMgr.self then
		jass.SetCameraField(jass[key], value, time or 0)
	end
end

--获取镜头属性
--	镜头属性
function player:getCameraField(key)
	return math.deg(jass.GetCameraField(jass[key]))
end

--设置镜头目标
function player:setCameraTarget(target, x, y)
	if self == g_playerMgr.self then
		jass.SetCameraTargetController(target and target.handle or 0, x or 0, y or 0, false)
	end
end

--旋转镜头
function player:rotateCamera(p, a, time)
	if self == g_playerMgr.self then
		local x, y = p:get_point():get()
		local a = math.rad(a)
		jass.SetCameraRotateMode(x, y, a, time)
	end
end

--获取镜头位置
function player:getCamera()
    return ac.point(jass.GetCameraTargetPositionX(), jass.GetCameraTargetPositionY())
end

--设置镜头可用区域
function player:setCameraBounds(...)
    if self == g_playerMgr.self then
        local minX, minY, maxX, maxY
        if select('#', ...) == 1 then
            local rct = rect.j_rect(...)
            minX, minY, maxX, maxY = rct:get()
        else
            minX, minY, maxX, maxY = ...
        end
        jass.SetCameraBounds(minX, minY, minX, maxY, maxX, maxY, maxX, minY)
    end
end
--endregion

--region UI
--允许UI
function player:enableUI()
	if self == g_playerMgr.self then
		jass.EnableUserUI(true)
	end
end

--禁止UI
function player:disableUI()
	if self == g_playerMgr.self then
		jass.EnableUserUI(false)
	end
end

--显示界面
--	[转换时间]
function player:showInterface(time)
	if self == g_playerMgr.self then
		jass.ShowInterface(true, time or 0)
	end
end

--隐藏界面
--	[转换时间]
function player:hideInterface(time)
	if self == g_playerMgr.self then
		jass.ShowInterface(false, time or 0)
	end
end

--禁止框选
function player:disableDragSelect()
	if self == g_playerMgr.self then
		jass.EnableDragSelect(false, false)
	end
end

--允许框选
function player:enableDragSelect()
	if self == g_playerMgr.self then
		jass.EnableDragSelect(true, true)
	end
end
--endregion

--获得颜色
function player:getColorWord()
	local i = self:get()
	return color_word[i]
end

--创建可见度修整器
--	圆心
--	半径
--	[是否可见]
--	[是否共享]
--	[是否覆盖单位视野]
function player:createFogmodifier(p, r, ...)
	local cir = circle.create(p, r)
	return fogmodifier.create(self, cir, ...)
end

--滤镜
function player:cinematic_filter(data)
	jass.SetCineFilterTexture(data.file or [[ReplaceableTextures\CameraMasks\DreamFilter_Mask.blp]])
	jass.SetCineFilterBlendMode(jass.BLEND_MODE_BLEND)
	jass.SetCineFilterTexMapFlags(jass.TEXMAP_FLAG_NONE)
	jass.SetCineFilterStartUV(0, 0, 1, 1)
	jass.SetCineFilterEndUV(0, 0, 1, 1)
	if data.start then
		jass.SetCineFilterStartColor(data.start[1] * 2.55, data.start[2] * 2.55, data.start[3] * 2.55, data.start[4] * 2.55)
	end
	if data.finish then
		jass.SetCineFilterEndColor(data.finish[1] * 2.55, data.finish[2] * 2.55, data.finish[3] * 2.55, data.finish[4] * 2.55)
	end
	jass.SetCineFilterDuration(data.time)
	if self == g_playerMgr.self then
		jass.DisplayCineFilter(true)
	end

	local player = self
	function data:remove()
		if player == g_playerMgr.self then
			jass.DisplayCineFilter(false)
		end
	end

	return data
end

-- 设置昼夜模型
function player:set_day(model)
	if self == g_playerMgr.self then
		jass.SetDayNightModels(model or default_model, 'Environment\\DNC\\DNCLordaeron\\DNCLordaeronUnit\\DNCLordaeronUnit.mdl')
	end
end

--region 创建单位(以玩家为参照)
--	单位id
--	位置
--	[朝向]
function player:create_unit(id, where, face)
    return g_unitMgr:create_unit(self, id, where, face)
end
--endregion

function player:create_dummy(id, where, face)
	local id = id or self:get_type_id()

	local team = self:get_team()
	local owner = self
	if g_playerMgr.com and g_playerMgr.com[team] then
		owner = g_playerMgr.com[team]
	end
    local u = g_unitMgr:create_unit(owner, id, where, face or 0)
	u._is_dummy = true
	u._dummy_point = u:getBornPoint()
	u._dummy_angle = face or 0
	if u:getAbilityLevel 'Aloc' == 0 then
		u:event_notify('单位-创建', u)
	end

	return u
end

--命令玩家选中单位
--	单位
function player:selectUnit(u)
    if self == g_playerMgr.self then
        jass.ClearSelection()
        jass.SelectUnit(u.handle, true)
    end
end

--命令玩家添加选择某单位
--	单位
function player:addSelect(u)
    if self == g_playerMgr.self then
        jass.SelectUnit(u.handle, true)
    end
end

--命令玩家取消选择某单位
--	单位
function player:removeSelect(u)
    if self == g_playerMgr.self then
        jass.SelectUnit(u.handle, false)
    end
end

--创建单位
--	id:单位id(字符串)
--	where:创建位置(type:point;type:circle;type:rect;type:unit)
--	face:面向角度
function player:createHero(name, where, face)
	local hero_data = ac.hero.hero_list[name].data
	local u = self:create_unit(hero_data.id, where, face)
	setmetatable(u, ac.hero)
	u:init(hero_data)

	u:add_ability 'AInv'
	u.hero_data = hero_data
	for k, v in pairs(u.attribute) do
		u:set(k, v)
	end
	return u
end

return player
